package com.av.client.frames;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDesktopPane;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.text.DateFormatter;
import javax.swing.text.NumberFormatter;

import org.jdesktop.swingx.JXDatePicker;
import org.jdesktop.swingx.JXErrorPane;
import org.jdesktop.swingx.error.ErrorInfo;

import com.av.client.AvDesktop;
import com.av.client.util.idioma.Error;
import com.av.client.util.idioma.Etiqueta;
import com.av.client.util.idioma.ManejadorIdiomas;
import com.av.client.util.idioma.ManejadorIdiomas.IdiomaEvent;
import com.av.client.util.idioma.ManejadorIdiomas.IdiomaEventListener;
import com.av.client.util.sesion.AdministradorSesion;
import com.av.db.dataobjects.Adeudo;
import com.av.db.dataobjects.ElementoCatalogo;
import com.av.db.dataobjects.Tarjeta;
import com.av.db.dataobjects.enums.Catalogo;
import com.av.exceptions.AvException;
import com.av.rmi.CatalogoAcciones;
import com.av.rmi.Parametro;
import com.av.rmi.Parametro.Tipo;

@SuppressWarnings("serial")
public class AdeudoFrame extends JInternalFrame {

	private static final int WIDTH = 700;
	private static final int HEIGHT = 300;

	private JLabel lblTipoAdeudo;
	private JLabel lblMonto;
	private JLabel lblTarjeta;
	private JLabel lblFecha;
	private JLabel lblHora;
	private JComboBox cboTipoAdeudo;
	private JComboBox cboTarjeta;
	private JFormattedTextField txtMonto;
	private JXDatePicker dtFecha;
	private JFormattedTextField txtHora;
	private JTable tblAdeudos;
	private JButton btnAgregar;
	private JButton btnActualizar;
	private JButton btnEliminar;
	private JButton btnCerrar;
	private JButton btnObtener;
	private JButton btnImagenes;

	private AdeudosModel im;
	private ManejadorIdiomas mi;
	private BotonHandler bh = new BotonHandler();
	private Adeudo adeudo;
	private Adeudo[] adeudos;

	public AdeudoFrame() {
		super();
		mi = ManejadorIdiomas.getInstance();
		initComponents();
		addListeners();
		cargarPermisos();
		cargarAdeudos();
		limpiarTextos();
	}// InfraccionesFrame

	private void cargarPermisos() {
		if (AdministradorSesion.getInstance().getSesionActiva() != null) {
			switch (AdministradorSesion.getInstance().getSesionActiva()
					.getUsuario().getRol()) {
			case CONDU:
				txtMonto.setEditable(false);
				cboTipoAdeudo.setEnabled(false);
				btnAgregar.setEnabled(false);
				btnActualizar.setEnabled(false);
				btnEliminar.setEnabled(false);
				break;
			case ADMIN:
				txtMonto.setEditable(true);
				cboTipoAdeudo.setEnabled(true);
				btnAgregar.setEnabled(true);
				btnActualizar.setEnabled(true);
				btnEliminar.setEnabled(true);
				break;
			}
		}
	}// cargarPermisos

	private void addListeners() {
		mi.addIdiomaEventListener(new IdiomaEventListener() {
			@Override
			public void changedIdiomaEvent(IdiomaEvent evt) {
				setLabels();
			}
		});

		tblAdeudos.getSelectionModel().addListSelectionListener(
				new ListSelectionListener() {
					@Override
					public void valueChanged(ListSelectionEvent e) {
						if (adeudos != null && tblAdeudos.getSelectedRow() >= 0
								&& tblAdeudos.getSelectedRow() < adeudos.length) {
							setAdeudo(adeudos[tblAdeudos.getSelectedRow()]);
						}
					}
				});

		btnAgregar.addActionListener(bh);
		btnEliminar.addActionListener(bh);
		btnActualizar.addActionListener(bh);
		btnCerrar.addActionListener(bh);
		btnObtener.addActionListener(bh);
		btnImagenes.addActionListener(bh);
		cboTipoAdeudo.addActionListener(bh);
	}// addListeners

	/**
	 * Funcion que restablece las etiquetas para todos los componentes
	 */
	private void setLabels() {
		setTitle(mi.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_TITLE));
		lblTipoAdeudo.setText(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_LBL_TIPO_ADEUDO));
		lblMonto.setText(mi.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_LBL_MONTO));
		lblTarjeta.setText(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_LBL_TARJETA));
		lblFecha.setText(mi.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_LBL_FECHA));
		txtMonto.setLocale(mi.getIdioma().getLocale());
		dtFecha.setLocale(mi.getIdioma().getLocale());
		lblHora.setText(mi.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_LBL_HORA));
		btnAgregar.setText(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_BTN_AGREGAR));
		btnEliminar.setText(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_BTN_ELIMINAR));
		btnActualizar.setText(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_BTN_ACTUALIZAR));
		btnCerrar.setText(mi.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_BTN_CERRAR));
		btnObtener.setText(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_BTN_OBTENER));
		String[] headers = (mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_TBL_ELEMENTOS_COLUMN_NAMES))
				.split(",");
		if (headers != null && tblAdeudos.getColumnCount() == headers.length) {
			for (int i = 0; i < tblAdeudos.getColumnCount(); i++) {
				tblAdeudos.getColumnModel().getColumn(i).setHeaderValue(
						headers[i]);
			}
		}
	}// setLabels

	/**
	 * Funcion que configura todos los componentes y su correcta colocacion
	 */
	private void initComponents() {
		setTitle(mi.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_TITLE));
		setSize(new Dimension());
		setLayout(new GridBagLayout());
		GridBagConstraints gc = new GridBagConstraints();

		gc.insets = new Insets(5, 5, 5, 5);
		gc.fill = GridBagConstraints.HORIZONTAL;

		// Fecha
		gc.gridy = 0;
		gc.gridx = 0;
		lblFecha = new JLabel(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_LBL_FECHA));
		add(lblFecha, gc);

		gc.gridx = 1;
		dtFecha = new JXDatePicker();
		dtFecha.setLocale(mi.getIdioma().getLocale());
		add(dtFecha, gc);

		// Hora
		gc.gridx = 2;
		lblHora = new JLabel(mi.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_LBL_HORA));
		add(lblHora, gc);

		gc.gridx = 3;
		txtHora = new JFormattedTextField(new DateFormatter(
				new SimpleDateFormat("HH:mm")));
		add(txtHora, gc);

		// Tipo de Adeudo
		gc.gridy = 1;
		gc.gridx = 0;
		lblTipoAdeudo = new JLabel(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_LBL_TIPO_ADEUDO));
		add(lblTipoAdeudo, gc);

		gc.gridx = 1;
		cboTipoAdeudo = new JComboBox(obtenerTipoAdeudo());
		add(cboTipoAdeudo, gc);

		// Monto
		gc.gridx = 2;
		lblMonto = new JLabel(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_LBL_MONTO));
		add(lblMonto, gc);

		gc.gridx = 3;
		txtMonto = new JFormattedTextField(new NumberFormatter(NumberFormat
				.getNumberInstance(mi.getIdioma().getLocale())));
		add(txtMonto, gc);

		// Tarjeta
		gc.gridy = 2;
		gc.gridx = 0;
		lblTarjeta = new JLabel(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_LBL_TARJETA));
		add(lblTarjeta, gc);

		gc.gridx = 1;
		gc.gridwidth = 3;
		cboTarjeta = new JComboBox(obtenerTarjetasActivas());
		add(cboTarjeta, gc);
		gc.gridwidth = 1;

		// Botones
		JPanel jpnl = new JPanel(new FlowLayout());

		btnAgregar = new JButton(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_BTN_AGREGAR));
		jpnl.add(btnAgregar);

		btnEliminar = new JButton(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_BTN_ELIMINAR));
		jpnl.add(btnEliminar);

		btnActualizar = new JButton(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_BTN_ACTUALIZAR));
		jpnl.add(btnActualizar);

		btnCerrar = new JButton(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_BTN_CERRAR));
		jpnl.add(btnCerrar);

		btnObtener = new JButton(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_BTN_OBTENER));
		jpnl.add(btnObtener);

		btnImagenes = new JButton(mi
				.obtenerEtiqueta(Etiqueta.ADEUDO_FRAME_BTN_IMAGENES));
		jpnl.add(btnImagenes);

		gc.gridy = 3;
		gc.gridx = 0;
		gc.gridwidth = 4;
		add(jpnl, gc);
		gc.gridwidth = 1;

		// Tabla de resultados

		gc.gridy = 4;
		gc.gridwidth = 4;
		gc.weightx = 1.0;
		gc.weighty = 1.0;
		gc.fill = GridBagConstraints.BOTH;
		im = new AdeudosModel(0);
		tblAdeudos = new JTable(im);
		tblAdeudos
				.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
		add(new JScrollPane(tblAdeudos), gc);

		setClosable(false);
		setSize(WIDTH, HEIGHT);
	}// initComponents

	private class AdeudosModel extends AbstractTableModel {
		private Map<Point, Object> lookup;
		private final int rows;
		private final int columns;
		private final String headers[];

		public AdeudosModel(int rows) {
			this.rows = rows;
			this.headers = mi.obtenerEtiqueta(
					Etiqueta.ADEUDO_FRAME_TBL_ELEMENTOS_COLUMN_NAMES)
					.split(",");
			this.columns = headers.length;

			lookup = new HashMap<Point, Object>();
		}

		public int getColumnCount() {
			return columns;
		}

		public int getRowCount() {
			return rows;
		}

		public String getColumnName(int column) {
			return headers[column];
		}

		public Object getValueAt(int row, int column) {
			return lookup.get(new Point(row, column));
		}

		public void setValueAt(Object value, int row, int column) {
			if ((rows < 0) || (columns < 0)) {
				throw new IllegalArgumentException("Invalid row/column setting");
			}
			if ((row < rows) && (column < columns)) {
				lookup.put(new Point(row, column), value);
			}
		}
	}

	/**
	 * Funcion que valida que los campos requeridos del formulario
	 * 
	 * @throws AvException
	 */
	private void validarTextos() throws AvException {
		if (cboTipoAdeudo.getSelectedIndex() < 0) {
			cboTipoAdeudo.requestFocus();
			throw new AvException(mi
					.obtenerError(Error.ADEUDO_CBO_TIPO_CATALOGO));
		}
		if (cboTarjeta.getSelectedIndex() < 0) {
			cboTarjeta.requestFocus();
			throw new AvException(mi
					.obtenerError(Error.ADEUDO_TXT_TARJETA_NULL));
		}

		if (txtMonto.getText() == null
				|| txtMonto.getText().trim().length() == 0) {
			txtMonto.requestFocus();
			throw new AvException(mi.obtenerError(Error.ADEUDO_TXT_MONTO));
		}
	}// validarTextos

	private Adeudo getAdeudo() {
		if (adeudo == null) {
			adeudo = new Adeudo();
		}

		adeudo.setElementoCatalogo((ElementoCatalogo) cboTipoAdeudo
				.getSelectedItem());
		adeudo.setTarjeta((Tarjeta) cboTarjeta.getSelectedItem());
		// adeudo.setCosto((Double) txtMonto.getValue());
		adeudo.setCosto(new Double(txtMonto.getText()));
		adeudo.setFecha(obtenerFecha());

		return adeudo;
	}// getAdeudo

	private void setAdeudo(Adeudo a) {
		if (a != null) {
			adeudo = a;

			cboTipoAdeudo.setSelectedItem(a.getElementoCatalogo());
			txtMonto.setValue(a.getCosto());
			cboTarjeta.setSelectedItem(a.getTarjeta());
			dtFecha.setDate(a.getFecha());
			txtHora.setValue(a.getFecha());
		}
	}// setAdeudo

	private void limpiarTextos() {
		cboTipoAdeudo.setSelectedIndex(-1);
		txtMonto.setText("");
		cboTarjeta.setSelectedIndex(-1);
		dtFecha.setDate(new Date());
		txtHora.setValue(new Date());
	}// limpiarTextos

	/**
	 * Clase creada para la administracion de acciones
	 * 
	 * @author Emmanuel Alcantara Garces
	 * 
	 */
	private class BotonHandler implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent ev) {
			Object o = ev.getSource();
			if (o instanceof JButton) {
				if (o == btnCerrar) {
					dispose();
				} else if (o == btnActualizar) {
					try {
						validarTextos();
						actualizarAdeudo();
					} catch (AvException e) {
						ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR",
								e.getMessage(), null, null, e, Level.WARNING,
								null);
						JXErrorPane
								.setDefaultLocale(mi.getIdioma().getLocale());
						JXErrorPane.showDialog(getParent(), info);
					}

				} else if (o == btnEliminar) {
					try {
						validarTextos();
						eliminarAdeudo();
					} catch (AvException e) {
						ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR",
								e.getMessage(), null, null, e, Level.WARNING,
								null);
						JXErrorPane
								.setDefaultLocale(mi.getIdioma().getLocale());
						JXErrorPane.showDialog(getParent(), info);
					}
				} else if (o == btnAgregar) {
					try {
						dtFecha.setDate(new Date());
						txtHora.setValue(new Date());
						validarTextos();
						agregarAdeudo();
					} catch (AvException e) {
						ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR",
								e.getMessage(), null, null, e, Level.WARNING,
								null);
						JXErrorPane
								.setDefaultLocale(mi.getIdioma().getLocale());
						JXErrorPane.showDialog(getParent(), info);
					}
				} else if (o == btnObtener) {
					cargarAdeudos();
				} else if (o == btnImagenes) {
					ImagenFrame i = new ImagenFrame();
					AvDesktop.getInstance().addDesktop(i);
					i.setVisible(true);
				}
			} else if (o instanceof JComboBox) {
				if (o == cboTipoAdeudo) {
					if (cboTipoAdeudo.getSelectedIndex() != -1) {
						ElementoCatalogo ec = (ElementoCatalogo) cboTipoAdeudo
								.getSelectedItem();
						txtMonto.setValue(ec.getCosto());
					}
				}
			}
		}// actionPerformed
	}// BotonHandler

	/**
	 * Funcion que agrega un adeudo a partir de los datos capturados
	 * 
	 * @throws AvException
	 */
	private void agregarAdeudo() throws AvException {
		Parametro p = new Parametro();
		p.setAccion(CatalogoAcciones.AGREGAR_ADEUDO);
		adeudo = new Adeudo();
		p.setValor(Tipo.INPUT, getAdeudo());
		AdministradorSesion.getInstance().getSesionActiva().ejecutar(p);
		limpiarTextos();
		cargarAdeudos();
	}// agregarAdeudo

	/**
	 * Funcion que actualiza un adeudo con los datos capturados
	 * 
	 * @throws AvException
	 */
	private void actualizarAdeudo() throws AvException {
		Parametro p = new Parametro();
		p.setAccion(CatalogoAcciones.ACTUALIZAR_ADEUDO);
		p.setValor(Tipo.INPUT, getAdeudo());
		AdministradorSesion.getInstance().getSesionActiva().ejecutar(p);
		limpiarTextos();
		cargarAdeudos();
	}// actualizarAdeudo

	/**
	 * Funcion que elimina el adeudo seleccionado
	 * 
	 * @throws AvException
	 */
	private void eliminarAdeudo() throws AvException {
		Parametro p = new Parametro();
		p.setAccion(CatalogoAcciones.ELIMINAR_ADEUDO);
		p.setValor(Tipo.INPUT, getAdeudo());
		AdministradorSesion.getInstance().getSesionActiva().ejecutar(p);
		limpiarTextos();
		cargarAdeudos();
	}// eliminarElementoCatalogo

	/**
	 * Funcion que carga en la tabla todos los adeudos registrados en el sistema
	 */
	private void cargarAdeudos() {
		Parametro p = new Parametro();
		if (AdministradorSesion.getInstance().getSesionActiva() != null) {
			try {
				p.setAccion(CatalogoAcciones.OBTENER_TODOS_ADEUDO);
				p = AdministradorSesion.getInstance().getSesionActiva()
						.ejecutar(p);
				if (p.getValor(Tipo.OUTPUT) != null) {
					adeudos = (Adeudo[]) p.getValor(Tipo.OUTPUT);
					im = new AdeudosModel(adeudos.length);
					int row = 0;
					for (Adeudo a : adeudos) {
						im.setValueAt(a.getTarjeta(), row, 0);
						im.setValueAt(a.getFecha(), row, 1);
						im.setValueAt(a.getElementoCatalogo().getDescripcion(),
								row, 2);
						im.setValueAt(a.getCosto(), row, 3);
						row++;
					}
					tblAdeudos.setModel(im);
				}
			} catch (AvException e) {
				ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR", e
						.getMessage(), null, null, e, Level.INFO, null);
				JXErrorPane.setDefaultLocale(mi.getIdioma().getLocale());
				JXErrorPane.showDialog(getParent(), info);
			}
		}
	}// cargarElementoCatalogo

	/**
	 * Obtiene la fecha y hora que el usuario a ingresado
	 * 
	 * @return Date
	 */
	private Date obtenerFecha() {
		Calendar c = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c.setTime(dtFecha.getDate());
		c2.setTime((Date) txtHora.getValue());
		c.set(Calendar.HOUR_OF_DAY, c2.get(Calendar.HOUR_OF_DAY));
		c.set(Calendar.MINUTE, c2.get(Calendar.MINUTE));

		return c.getTime();
	}// obtenerFecha

	/**
	 * Obtiene la tipos de adeudo de acuerdo al usuario firmado
	 * 
	 * @return ElementoCatalogo[]
	 * @throws AvException
	 */
	private ElementoCatalogo[] obtenerTipoAdeudo() {
		Parametro p = new Parametro();
		if (AdministradorSesion.getInstance().getSesionActiva() != null) {
			try {

				switch (AdministradorSesion.getInstance().getSesionActiva()
						.getUsuario().getRol()) {
				case ADMIN:
					p
							.setAccion(CatalogoAcciones.OBTENER_ACTIVOS_ELEMENTO_CATALOGO);
					break;
				case GUARD:
					p
							.setAccion(CatalogoAcciones.OBTENER_CATALOGO_ELEMENTO_CATALOGO);
					p.setValor(Tipo.INPUT, (Catalogo) Catalogo.INFRACCION);
					break;
				case CONDU:
					p
							.setAccion(CatalogoAcciones.OBTENER_ACTIVOS_ELEMENTO_CATALOGO);
					break;
				default:
					p
							.setAccion(CatalogoAcciones.OBTENER_CATALOGO_ELEMENTO_CATALOGO);
					p.setValor(Tipo.INPUT, (Catalogo) Catalogo.INFRACCION);
					break;
				}
				p = AdministradorSesion.getInstance().getSesionActiva()
						.ejecutar(p);
			} catch (AvException e) {
				cboTipoAdeudo = new JComboBox();
				ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR", e
						.getMessage(), null, null, e, Level.WARNING, null);
				JXErrorPane.setDefaultLocale(mi.getIdioma().getLocale());
				JXErrorPane.showDialog(getParent(), info);
			}
			if (p.getValor(Tipo.OUTPUT) != null) {
				return (ElementoCatalogo[]) p.getValor(Tipo.OUTPUT);
			}
		}
		return new ElementoCatalogo[0];
	}

	/**
	 * Funcion que obtiene todas las tarjetas activas del sistema
	 * 
	 * @return
	 */
	private Tarjeta[] obtenerTarjetasActivas() {
		Tarjeta[] tmp = new Tarjeta[1];
		Parametro p = new Parametro();

		if (AdministradorSesion.getInstance().getSesionActiva() != null) {
			try {
				p.setAccion(CatalogoAcciones.OBTENER_ACTIVOS_TARJETA);
				p = AdministradorSesion.getInstance().getSesionActiva()
						.ejecutar(p);
				if (p.getValor(Tipo.OUTPUT) != null) {
					tmp = (Tarjeta[]) p.getValor(Tipo.OUTPUT);
				}
			} catch (AvException e) {
				ErrorInfo info = new ErrorInfo(getTitle() + " - ERROR", e
						.getMessage(), null, null, e, Level.INFO, null);
				JXErrorPane.setDefaultLocale(mi.getIdioma().getLocale());
				JXErrorPane.showDialog(getParent(), info);
			}
		}

		return tmp;
	}// obtenerTarjetasActivas

	public static void main(String[] args) {
		JFrame tmp = new JFrame("AdeudosFrame");
		tmp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JDesktopPane desktop = new JDesktopPane();
		desktop.setBackground(Color.GRAY);
		desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
		tmp.setContentPane(desktop);

		AdeudoFrame ecf = new AdeudoFrame();
		ecf.setVisible(true);
		desktop.add(ecf);
		try {
			ecf.setSelected(true);
		} catch (PropertyVetoException e) {
		}
		tmp.setSize(new Dimension(ecf.getWidth() + 100, ecf.getHeight() + 100));
		tmp.setVisible(true);
	}// main
}// AdeudoFrame